package com.kamistoat.meimeimall.meimeimallorder.listener;

import com.alipay.api.AlipayApiException;
import com.alipay.api.internal.util.AlipaySignature;
import com.kamistoat.meimeimall.common.To.paymentTo.PayAsyncTo;
import com.kamistoat.meimeimall.common.annotation.DubboAndHTTPExceptionCatch;
import com.kamistoat.meimeimall.common.utils.R;
import com.kamistoat.meimeimall.meimeimallorder.config.AlipayTemplate;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.io.UnsupportedEncodingException;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * 监听支付回调。其实是个Controller
 */
@Api(tags = "监听支付回调")
@RestController
@RequestMapping("order")
public class OrderPayCallbackListener {
    protected Logger logger = LoggerFactory.getLogger(OrderPayCallbackListener.class);

    @Autowired
    RabbitTemplate rabbitTemplate;
    @Autowired
    AlipayTemplate alipayTemplate;


    /**
     * 收到第三方支付的的支付异步回调通知。验签通过后推送消息到消息队列。
     * 之后的支付状态流转由下游的 {@link OrderPayMQListener} 完成。
     *
     * @return
     */
    @ApiOperation("支付宝支付回调")
    @PostMapping("/payed_notify")
    @ResponseBody
    public String handleAlipayed(HttpServletRequest request) throws AlipayApiException, UnsupportedEncodingException, ParseException {
        logger.info("收到支付宝异步通知");
        // 验证签名
        //获取支付宝POST过来反馈信息
        Map<String, String> params = new HashMap<String, String>();
        Map<String, String[]> requestParams = request.getParameterMap();
        for (String name : requestParams.keySet()) {
            String[] values = (String[]) requestParams.get(name);
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i]
                        : valueStr + values[i] + ",";
            }
            //乱码解决，这段代码在出现乱码时使用。如果mysign和sign不相等也可以使用这段代码转化
            //valueStr = new String(valueStr.getBytes("ISO-8859-1"), "gbk");
            params.put(name, valueStr);
        }
        //获取支付宝的通知返回参数，可参考技术文档中页面跳转同步通知参数列表(以下仅供参考)//
        //商户订单号

        String out_trade_no = new String(request.getParameter("out_trade_no").getBytes("ISO-8859-1"), "UTF-8");
        //支付宝交易号

        String trade_no = new String(request.getParameter("trade_no").getBytes("ISO-8859-1"), "UTF-8");

        //交易状态
        String trade_status = new String(request.getParameter("trade_status").getBytes("ISO-8859-1"), "UTF-8");

        // 交易金额
        String buyer_pay_amount = new String(request.getParameter("buyer_pay_amount").getBytes("ISO-8859-1"), "UTF-8");

        // 交易时间
        String notify_time_string = new String(request.getParameter("notify_time").getBytes("ISO-8859-1"), "UTF-8");
        DateFormat dataFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date notify_time = dataFormat.parse(notify_time_string);

        //获取支付宝的通知返回参数，可参考技术文档中页面跳转同步通知参数列表(以上仅供参考)//
        //计算得出通知验证结果
        //boolean AlipaySignature.rsaCheckV1(Map<String, String> params, String publicKey, String charset, String sign_type)
        boolean verify_result = AlipaySignature.rsaCheckV1(
                params,
                alipayTemplate.getAlipay_public_key(),
                alipayTemplate.getCharset(),
                alipayTemplate.getSign_type());

        /**
         * 支付宝验签通过
         */
        if (verify_result) {
            logger.info("支付宝签名验证成功，推送消息给消息队列，前端开始监听处理结果队列");
            PayAsyncTo payAsyncTo = new PayAsyncTo();
            payAsyncTo.setTrade_no(trade_no);
            payAsyncTo.setOut_trade_no(out_trade_no);
            payAsyncTo.setTrade_status(trade_status);
            payAsyncTo.setNotify_time(notify_time);
            payAsyncTo.setTotal_amount(buyer_pay_amount);
            try{
                rabbitTemplate.convertAndSend("order-event-exchange", "order.pay.callback", payAsyncTo);
                return "success";
            }catch (Exception e){
                e.printStackTrace();
                return "fail";
            }
        } else {
            //out.println("fail");
            logger.error("支付宝签名验证失败");
            return "fail";
        }
    }


    /**
     * 绕过真实支付，手动发送支付回调给该接口。仅开发阶段使用。
     * 之后的支付状态流转由下游的 {@link OrderPayMQListener} 完成。
     *
     * @return
     */
    @ApiOperation("虚拟支付回调，绕过真实支付接口")
    @PostMapping("/payed_notify_unreal")
    @ResponseBody
    @DubboAndHTTPExceptionCatch
    public R handlePayedUnreal(String orderSn, String payment) {
        logger.info("接收到支付回调");
        PayAsyncTo payAsyncTo = new PayAsyncTo();
        String trade_no = "prod_" + UUID.randomUUID().toString();
        payAsyncTo.setTrade_no(trade_no);
        payAsyncTo.setOut_trade_no(orderSn);
        payAsyncTo.setTrade_status("TRADE_SUCCESS");
        payAsyncTo.setNotify_time(new Date());
        payAsyncTo.setTotal_amount(payment);
        payAsyncTo.setSubject("模拟支付接口");
        rabbitTemplate.convertAndSend("order-event-exchange", "order.pay.callback", payAsyncTo);
        return R.ok("已推送支付消息给消息队列，前端开始监听处理结果队列");
    }
}
